﻿namespace Groundwork.Extensions
{
	using System;
	using System.Threading;
	using Groundwork;
    using Groundwork.Core.Threading;

	/// <summary>
	/// Description of Threading.
	/// </summary>
	public static class Locking
	{
        /// <summary>
        /// Locks the specified value.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value">The value.</param>
        /// <param name="operation">The operation.</param>
		public static void Lock<T>(this T value, Action<T> operation)
		{
			value.ThrowIfNull("value");
			lock(value)
			{
				try
				{
					operation(value);
				}
				catch
				{
					throw;
				}
			}
		}

        /// <summary>
        /// Create a mutex and performs the Action specified in Operation. During the mutext operation 
        /// the value object is locked.
        /// </summary>
        /// <param name="value">value to lock during mutex</param>
        /// <param name="operation">Action delegate operation to perform</param>
        public static void MutextLock<T>(this T value, Action<T> operation)
        {
            value.ThrowIfNull("value");
            using (AquireMutext synclocking = new AquireMutext("MutexLock"))
            {
                lock (value)
                {
                    try
                    {
                        operation(value);
                    }
                    catch
                    {
                        throw;
                    }
                    finally
                    {
                        synclocking.Release();
                    }

                }
            }
        }	

		/// <summary>
        /// Create a mutex and performs the Action specified in Operation. During the mutext operation 
		/// the value object is locked.
		/// </summary>
		/// <param name="value">value to lock during mutex</param>
		/// <param name="operation">Action delegate operation to perform</param>
    	public static void MutextLock<T>(this T value, TimeSpan expiry, Action<T> operation)
    	{
    		value.ThrowIfNull("value");
            operation.ThrowIfNull("operation");
    		using(AquireMutext synclocking = new AquireMutext("MutextLock", expiry))
    		{
    			lock(value)
    			{
    		   		try
    				{
    					operation(value);	
    				}
    				catch
    				{
    					throw;
    				}
    				finally
    				{
    					synclocking.Release();
    				}

    			}
    		}    	
    	}

        /// <summary>
        /// Threads the block.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value">The value.</param>
        /// <param name="operation">The operation.</param>
    	public static void ThreadBlock<T>(this T value, Action<T> operation)
    	{
    		value.ThrowIfNull("value");
            operation.ThrowIfNull("operation");
    		using(ThreadLocking locking = new ThreadLocking("ThreadLock"))
    		{
    			lock(value)
    			{
    		   		try
    				{
                        operation(value);	
    				}
    				catch
    				{
    					throw;
    				}
    				finally
    				{
    					locking.Release();
    				}

    			}
    		}   
    	}

        /// <summary>
        /// Threads the block.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value">The value.</param>
        /// <param name="expiry">The expiry.</param>
        /// <param name="operation">The operation.</param>
    	public static void ThreadBlock<T>(this T value, TimeSpan expiry , Action<T> operation)
    	{
            value.ThrowIfNull("value");
            operation.ThrowIfNull("operation"); 
    		using(ThreadLocking locking = new ThreadLocking("ThreadLock", expiry))
    		{
    			lock(value)
    			{
    		   		try
    				{
    					operation(value);	
    				}
    				catch
    				{
    					throw;
    				}
    				finally
    				{
    					locking.Release();
    				}

    			}
    		}   
    	}
	}
}
